<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>NINJA!</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }

        #results li.pass {
            flex: 0;
            color: green;
        }

        #results li.fail {
            flex: 0;
            color: red;
            text-decoration: line-through;
        }
    </style>
</head>
<body>

<ui id="results"></ui>

<script>
    //断言
    function assert(value, desc) {
        var li = document.createElement('li');
        li.className = value ? 'pass' : 'fail';
        li.appendChild(document.createTextNode(desc));
        document.getElementById('results').appendChild(li);
    }

    //A simple closure
    var outerValue = 'ninja';
    var later;
//    function outerFunction() {
//        assert(outerValue == 'ninja','I can see the ninja.')
//    }
//    outerFunction();

    //闭包示例

//    function outerFunction() {
//        var innerValue = 'samurai';
//        function innerFunction() {
//            assert(outerValue,'I can see the ninja.');
//            assert(innerValue,'I can see the samurai')
//        }
//        later = innerFunction;
//    }
//    outerFunction();
//    later();  //由于later是函数outerFunction的内部变量,所以外部访问不到~

    //闭包可以访问到什么内容
    function outerFunction() {
        var innerValue = 'samurai';

        function innerFunction(paramValue) {
            assert(outerValue,'Inner can see the ninja.');
            assert(innerValue,'Inner can see the samurai.');
            assert(paramValue,'Inner can see the wakizashi.');
            assert(tooLate,'Inner can see the ronin.');
        }

        later = innerFunction;
    }
    assert(!tooLate,"Outer can't see the ronin"); //未声明之前在相同作用域内不能提前引用.

    var tooLate = 'ronin';

    outerFunction();
    later('wakizashi');//理由同上

    //闭包模拟私有变量
    function Ninja() {
        var feints = 0;
        this.getFeints = function () {
            return feints;
        };
        this.feint = function () {
            feints++;
        };
    }

    var ninja = new Ninja();

    ninja.feint();

    assert(ninja.getFeints() == 1,"We're able to acess the internal feint count.");
    assert(ninja.feints === undefined ,"And the private data is inaccessible to us.")

</script>
</body>
</html>